package com.gxa.hualianeshop.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxa.hualianeshop.component.ActiveMQProducer;
import com.gxa.hualianeshop.entity.dto.CartDto;
import com.gxa.hualianeshop.entity.pojo.CartItem;
import com.gxa.hualianeshop.entity.pojo.Order;
import com.gxa.hualianeshop.mapper.OrderMapper;
import com.gxa.hualianeshop.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p>
 * 订单实现类
 *
 * 购物车下单
 * 当执行创建订单过程中, 也都需要考虑并发问题和性能的影响
 * 通过加锁控制订单创建过程中, 多种商品扣库存
 * 两种方式: 1. 重入锁  2. 数据库(SELECT ... FOR UPDATE )
 *
 * 其中,第二种方式:
 * 确保在事务中其他并发操作无法修改该行的数据
 *
 * 秒杀/特价商品抢购下单
 * </p>
 *
 * @author gxa
 * @since 2023-07-05
 */
@Service
@Transactional(rollbackFor = Throwable.class)
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {


    /**
     * 常规的订单创建流程
     *
     * @param cartDto 购物车dto对象
     * @return
     */
    @Override
    public Order create(CartDto cartDto) {

        // 获取用户id
        Long userId = cartDto.getUserId();

        // 获取OrderItemList(仅添加有货商品)
        List<CartItem> cartItemList = cartDto.getCartItemList();

        // 创建一个重入锁(可以有效防止死锁)
        Lock lock = new ReentrantLock();

        try {
            //加锁
            lock.lock();
            //遍历商品
            for (CartItem cartItem : cartItemList) {
                String skuId = cartItem.getSkuId();


                // 从数据库查询商品数量,如果有任何一个商品不满足,下单失败
                Integer num = null;
                if (num < cartItem.getNum()) {
                    // 如果库存不足，抛出异常
                    // throw new BizException(ResultCode.LACK_SPU_NUM);
                }
                // 更新数据库中的库存数量

            }
            // 生成订单,创建订单编号(雪花),生成订单基础数据,完成添加
            Order order = new Order();


        }finally{
            lock.unlock();
        }

        return null;
    }


    @Autowired
    ActiveMQProducer producer;
    /**
     * 当生成雪花算法的订单编号,并返回给了前端
     * 把订单编号+用户编号+ 购物车信息(CartItem)或缓存中的购物信息(秒杀等购买直接进redis) 存入redis
     * 这里需注意: 淘宝的秒杀(数量少)直接进入支付页 / 京东的秒杀(时间长)会进入购物车
     * 将订单编号存入消息队列
     * 再准备一个监听器, 监听生成订单到数据库的队列
     * 监听时,将订单信息写入数据库, 删除redis缓存的订单数据
     * 返回订单编号给前端
     * @param orderId 订单编号
     * @return
     */
    @Override
    public Order concurrentCreate(Long orderId){

        // 从缓存中读取商品信息

        // 把秒杀商品信息生成订单 Sku
        // orderMapper 执行save方法





        return null;
    }
}
